package com.hz.tgb.response.restful.exception.util;

import com.hz.tgb.response.restful.AppCode;
import com.hz.tgb.response.restful.exception.ErrorException;
import com.hz.tgb.response.restful.exception.InfoException;
import com.hz.tgb.response.restful.exception.WarnException;
import org.apache.commons.lang.ArrayUtils;
import org.slf4j.event.Level;

import java.util.Collection;
import java.util.Map;

/**
 * 抛出异常工具类
 *
 * @author hezhao created on 2019/12/7 10:04
 */
public class ExceptionUtil {

    private Level level;

    private ExceptionUtil(Level level) {
        this.level = level;
    }

    /**
     * 登记式/静态内部类
     */
    private static class SingletonHolder {
        private static final ExceptionUtil INFO_INSTANCE = new ExceptionUtil(Level.INFO);
        private static final ExceptionUtil WARN_INSTANCE = new ExceptionUtil(Level.WARN);
        private static final ExceptionUtil ERROR_INSTANCE = new ExceptionUtil(Level.ERROR);
    }

    public static ExceptionUtil info() {
        return SingletonHolder.INFO_INSTANCE;
    }

    public static ExceptionUtil warn() {
        return SingletonHolder.WARN_INSTANCE;
    }

    public static ExceptionUtil error() {
        return SingletonHolder.ERROR_INSTANCE;
    }

    // ---------------------------------实例方法---------------------------------
    /**
     * 如果flag为true, 则抛出异常
     * @param flag
     * @param appCode
     * @param args 替换异常描述中的参数
     */
    public void checkArgument(boolean flag, AppCode appCode, Object... args) {
        if (flag) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果flag为false, 则抛出异常
     * @param flag 判断逻辑
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public void checkNotArgument(boolean flag, AppCode appCode, Object... args) {
        if (!flag) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果obj为null, 则抛出异常
     * @param obj 对象
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public void isNull(Object obj, AppCode appCode, Object... args) {
        if (obj == null) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果obj不为null, 则抛出异常
     * @param obj 对象
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public void notNull(Object obj, AppCode appCode, Object... args) {
        if (obj != null) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果字符串为空, 则抛出异常
     * @param str 字符串
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public void isEmpty(String str, AppCode appCode, Object... args) {
        if (str == null || str.isEmpty()) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果字符串不为空, 则抛出异常
     * @param str 字符串
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public void notEmpty(String str, AppCode appCode, Object... args) {
        if (str != null && !str.isEmpty()) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果集合为空, 则抛出异常
     * @param collection 集合
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public <T> void isEmpty(Collection<T> collection, AppCode appCode, Object... args) {
        if (collection == null || collection.isEmpty()) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果集合不为空, 则抛出异常
     * @param collection 集合
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public <T> void notEmpty(Collection<T> collection, AppCode appCode, Object... args) {
        if (collection != null && !collection.isEmpty()) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果数组为空, 则抛出异常
     * @param array 数组
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public <T> void isEmpty(T[] array, AppCode appCode, Object... args) {
        if (array == null || array.length == 0) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果数组不为空, 则抛出异常
     * @param array 数组
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public <T> void notEmpty(T[] array, AppCode appCode, Object... args) {
        if (array != null && array.length != 0) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果Map集合为空, 则抛出异常
     * @param map Map集合
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public <K, V> void isEmpty(Map<K, V> map, AppCode appCode, Object... args) {
        if (map == null || map.isEmpty()) {
            throwExec(appCode, args);
        }
    }

    /**
     * 如果Map集合不为空, 则抛出异常
     * @param map Map集合
     * @param appCode 错误码
     * @param args 替换异常描述中的参数
     */
    public <K, V> void notEmpty(Map<K, V> map, AppCode appCode, Object... args) {
        if (map != null && !map.isEmpty()) {
            throwExec(appCode, args);
        }
    }

    /**
     * 抛出异常，可替换异常描述中的参数
     * @param appCode 错误码
     * @param args 参数
     */
    public void throwExec(AppCode appCode, Object... args) {
        if (ArrayUtils.isEmpty(args)) {
            if (level == Level.INFO) {
                throw new InfoException(appCode);
            } else if (level == Level.WARN) {
                throw new WarnException(appCode);
            } else if (level == Level.ERROR) {
                throw new ErrorException(appCode);
            }
        }

        String message = String.format(appCode.getMessage(), args);
        if (level == Level.INFO) {
            throw new InfoException(appCode.getCode(), message);
        } else if (level == Level.WARN) {
            throw new WarnException(appCode.getCode(), message);
        } else if (level == Level.ERROR) {
            throw new ErrorException(appCode.getCode(), message);
        }
    }

}
